package com.xqboss.apps.controller.user;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xqboss.apps.constant.Config;
import com.xqboss.apps.convert.user.WithdrawRecordConverter;
import com.xqboss.apps.domain.consumer.ConsumerRealName;
import com.xqboss.apps.domain.order.OrderMain;
import com.xqboss.apps.domain.param.AesParams;
import com.xqboss.apps.domain.user.*;
import com.xqboss.apps.dto.order.CreateOrderDto;
import com.xqboss.apps.dto.user.*;
import com.xqboss.apps.enums.market.MarketTypeEnum;
import com.xqboss.apps.enums.order.OrderTypeEnum;
import com.xqboss.apps.enums.user.PayTypeEnum;
import com.xqboss.apps.enums.user.UserWalletEnum;
import com.xqboss.apps.enums.user.WalletChangeTypeEnum;
import com.xqboss.apps.service.consumer.ConsumerRealNameService;
import com.xqboss.apps.service.market.MarketService;
import com.xqboss.apps.service.order.OrderService;
import com.xqboss.apps.service.order.PayApplyService;
import com.xqboss.apps.service.sys.ConfigService;
import com.xqboss.apps.service.sys.SysUserLidouRecordService;
import com.xqboss.apps.service.user.*;
import com.xqboss.apps.vo.pay.PayInfoVo;
import com.xqboss.apps.vo.sys.AppRechargeProfileVo;
import com.xqboss.apps.vo.user.*;
import com.xqboss.common.annotation.RepeatSubmit;
import com.xqboss.common.constant.HttpStatus;
import com.xqboss.common.core.controller.BaseController;
import com.xqboss.common.core.domain.R;
import com.xqboss.common.core.domain.entity.SysUser;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.SecurityUtils;
import com.xqboss.common.utils.aes.AesUtil;
import com.xqboss.common.utils.uuid.IdUtils;
import com.xqboss.system.service.ISysConfigService;
import com.xqboss.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 用户钱包相关控制器
 * </p>
 *
 * @author Trent
 * @date 2023/8/17
 */

@Slf4j
@Api(tags = "钱包-用户钱包管理")
@RestController
@RequestMapping("/user/wallet")
public class UserWalletController extends BaseController {

    @Autowired
    private SysUserWalletService userWalletService;

    @Autowired
    private SysUserWalletRecordService sysUserWalletRecordService;

    @Autowired
    private WithdrawRecordConverter withdrawRecordConverter;

    @Autowired
    private OrderService orderService;

    @Autowired
    private PayApplyService payApplyService;

    @Autowired
    private ConsumerRealNameService realNameService;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private YeepayWalletService yeepayWalletService;

    @Lazy
    @Autowired
    private MarketService marketService;

    @Lazy
    @Autowired
    private ConfigService configService;

    @Autowired
    private SysUserHotbeansRecordService basicService;

    @Autowired
    private UserIdentityPermWrenchPresenterService userIdentityPermWrenchPresenterService;

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private UserAssetWrenchRecordService userAssetWrenchRecordService;
    @Autowired
    private SysUserHotbeansRecordService sysUserHotbeansRecordService;

    @Autowired
    private UserIdentityPermBasicService userIdentityPermBasicService;
    @Autowired
    private UserAssetWrenchService userAssetWrenchService;

    @Autowired
    private UserAssetLidouRecordService UserAssetLidouRecordService;

    @Autowired
    private UserIdentityPermLidouService userIdentityPermLidouService;

    @Autowired
    private SysUserLidouRecordService sysUserLidouRecordService;


    /**
     * 余额充值
     *
     * @return
     */

    @RepeatSubmit(interval = 1000, justUrl = true)
    @ApiOperation("余额充值")
    @PostMapping("recharge")
    public R<PayInfoVo> recharge(@Validated @RequestBody WalletRechargeDto params) {
        Long identityId = sysUserHotbeansRecordService.getUserIdentity(getUserId());
        LambdaQueryWrapper<UserIdentityPermBasic> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserIdentityPermBasic::getIdentityId,identityId);
        // 查出该身份配置是否有无视充值开关权限
        UserIdentityPermBasic permBasic = userIdentityPermBasicService.getBaseMapper().selectOne(wrapper);
        Boolean isRechargeIgnore = permBasic.getIsRechargeIgnore();
        // 经商者及以上无视充值开关
        Boolean enable = sysConfigService.getValue(Config.Sys.Recharge.充值功能开启状态);
        if (!isRechargeIgnore){
            // 如果isRechargeIgnore != true,则表明用户非经商者及以上
            if (!enable) {
                throw new ServiceException("充值通道维护中~");
            }
        }
        Boolean allowInputAmount = sysConfigService.getValue(Config.Sys.Recharge.自定义充值);
        if (!allowInputAmount) {
            // 禁用自定义金额
            if (Objects.isNull(params.getRechargeId())) {
                throw new ServiceException("暂不支持自定义充值金额！");
            }
        }
        // 充值支付方式
        List<Integer> payType = sysConfigService.getValue(Config.Sys.Recharge.支付方式);
        // 支付方式比对
        if (payType == null || !payType.contains(params.getPayWay().getValue())) {
            throw new ServiceException("暂不支持该支付方式！");
        }

        //实名用户才能充值
        realNameService.requireRealName(getUserId());

        if (params.getPayWay() == PayTypeEnum.Wallet) {
            throw new ServiceException("充值不支持钱包支付！");
        }
        CreateOrderDto orderParams = new CreateOrderDto();
        orderParams.setSourceId(params.getRechargeId());
        orderParams.setOrderType(OrderTypeEnum.Recharge);
        orderParams.setQuantity(1);
        orderParams.setToken(IdUtils.fastSimpleUUID());
        orderParams.setPayType(params.getPayWay());
        orderParams.setPrice(params.getPrice());
        OrderMain order = orderService.createOrder(SecurityUtils.getUserId(), orderParams);

        PayInfoVo payInfoVo = payApplyService.applyPay(order.getId(), getUserId(), params.getPayWay());
        return R.ok(payInfoVo);
    }

    /**
     * 钱包充值配置
     *
     * @return
     */
    @ApiOperation("钱包充值配置")
    @GetMapping("recharge-config")
    public R<AppRechargeProfileVo> rechargeConfig() {
        AppRechargeProfileVo profile = configService.getAppRechargeProfile();
        return R.ok(profile);
    }


    /**
     * 提现详情
     *
     * @return
     */
    @ApiOperation("钱包详情")
    @GetMapping("detail")
    public R<SysUserWallet> walletDetail(@Validated AppUserWalletDetailDto params) {
        SysUserWallet wallet = userWalletService.getWallet(getUserId(), params.getType());
        return R.ok(wallet);
    }

    /**
     * 提现详情
     *
     * @return
     */
    @ApiOperation("现金钱包信息")
    @GetMapping("cash-info")
    public R<CashInfoVo> cashInfo() {
        CashInfoVo vo = new CashInfoVo();
        Long userId = getUserId();
        SysUserWallet wallet = userWalletService.getWallet(userId, UserWalletEnum.CASH);
        vo.setPlatformBalance(wallet.getAmount());
        YeepayWallet userWallet = yeepayWalletService.getUserWallet(userId);
        vo.setYeepayStatus(userWallet != null);
        return R.ok(vo);
    }


    @RepeatSubmit(interval = 1000, justUrl = true)
    @ApiOperation("易宝钱包登录/注册")
    @GetMapping("yeepay-index")
    public R<YeepayIndexVo> yeepayIndex() {
        YeepayIndexVo vo = new YeepayIndexVo();
        SysUser user = SecurityUtils.getLoginUser().getUser();
        String url = yeepayWalletService.getWalletIndex(user);
        vo.setUrl(url);
        return R.ok(vo);
    }

    @ApiOperation("钱包变动记录")
    @GetMapping("record-list")
    public R<List<WithdrawRecordVo>> getRecordList(@Validated WithdrawRecordListDto params) {
        params.setSortAsc(false);
        params.setOrderByColumn("id");
        params.setUserId(getUserId());
//        params.setUserId(1701577341501919232L);
        params.startPageAndOrder();
        List<SysUserWalletRecordVo> list;
        if (params.getWalletType() == UserWalletEnum.WRENCH){
            list = userAssetWrenchRecordService.getRecordList(params);
        } else if (params.getWalletType() == UserWalletEnum.LIDOU){
            list = UserAssetLidouRecordService.getRecordList(params);
        } else {
            list = sysUserWalletRecordService.getRecordList(params);
        }
        List<WithdrawRecordVo> voList = withdrawRecordConverter.toVoList(list);
        voList.forEach(vo -> {
            if (vo.getChangeType() != WalletChangeTypeEnum.ORDER_PAY
                    && vo.getChangeType() != WalletChangeTypeEnum.ORDER_REFUND
                    && vo.getChangeType() != WalletChangeTypeEnum.WITHDRAW
                    && vo.getChangeType() != WalletChangeTypeEnum.RECHARGE
                    && vo.getChangeType() != WalletChangeTypeEnum.MARKET_INCOME) {
                vo.setOrderId(null);
            }
            // 单独处理游戏的图标，需要修改changetype 101 102. TODO 后面需要前端加图标判断
            if (vo.getChangeType() == WalletChangeTypeEnum.DTS_BET) {
                vo.setChangeType(WalletChangeTypeEnum.WRENCH_TEAM_MATERIAL_PROMOTION);
            } else if (vo.getChangeType() == WalletChangeTypeEnum.DTS_SETTLE) {
                vo.setChangeType(WalletChangeTypeEnum.WRENCH_RECEIVE);
            }
        });


        return R.ok(voList, list);
    }


    /**
     * 热豆市场信息
     *
     * @return
     */
    @ApiOperation("获取热豆市场信息")
    @GetMapping("integer-info")
    public R<IntegerInfoVo> integerInfo() {
        IntegerInfoVo vo = new IntegerInfoVo();
        Long userId = getUserId();
        SysUserWallet wallet = userWalletService.getWallet(userId, UserWalletEnum.INTEGRAL);
        vo.setIntegerBalance(wallet.getAmount());
        int saleStock = marketService.getSaleStock(userId, MarketTypeEnum.MATERIAL, UserWalletEnum.INTEGRAL);
        vo.setMarketIntegerBalance(BigDecimal.valueOf(saleStock));

        UserAssetWrench assetWrench = userAssetWrenchService.getByUserId(userId);
        vo.setWrenchIntegerBalance(assetWrench.getAmount());
        int saleWrenchStock =  marketService.getWrenchSaleStock(userId,MarketTypeEnum.MATERIAL,UserWalletEnum.WRENCH);
        vo.setMarketWrenchIntegerBalance(BigDecimal.valueOf(saleWrenchStock));
        return R.ok(vo);
    }

    /**
     * 用户热豆转增前置信息
     *
     * @return
     */
    @RepeatSubmit(interval = 1000, justUrl = true)
    @GetMapping("/hotBeansGiveBefore")
    @ApiOperation("用户热豆转赠前置信息")
    public R<HotBeansGiveBeforeVo> hotBeansGiveBefore() {
        Long userId = getUserId();
//        userId=1L;
        // 获取用户身份id
        Long identityId = basicService.getUserIdentity(userId);
        HotBeansGiveBeforeVo vo = basicService.hotBeansGiveBefore(identityId, userId);
        return R.ok(vo);
    }

    /**
     * 用户扳手转增前置信息
     *
     * @return
     */
    @RepeatSubmit(interval = 1000, justUrl = true)
    @GetMapping("/wrenchGiveBefore")
    @ApiOperation("用户扳手转赠前置信息")
    public R<HotBeansGiveBeforeVo> wrenchGiveBefore() {
        Long userId = getUserId();
        // 获取用户身份id
        Long identityId = basicService.getUserIdentity(userId);
        HotBeansGiveBeforeVo vo = userIdentityPermWrenchPresenterService.wrenchGiveBefore(identityId, userId);
        return R.ok(vo);
    }

    @GetMapping("/giveBefore")
    @ApiOperation("用户资产转赠前置信息")
    public R<HotBeansGiveBeforeVo> giveBefore(UserWalletEnum walletEnum) {
        Long userId = getUserId();
        // 获取用户身份id
        Long identityId = basicService.getUserIdentity(userId);
        HotBeansGiveBeforeVo vo = new HotBeansGiveBeforeVo();
        switch (walletEnum) {
            case INTEGRAL:
                vo = basicService.hotBeansGiveBefore(identityId, userId);
                break;
            case WRENCH:
                vo = userIdentityPermWrenchPresenterService.wrenchGiveBefore(identityId, userId);
                break;
            case LIDOU:
                vo = userIdentityPermLidouService.userInfo(identityId, userId);
                break;
        }
        return R.ok(vo);
    }


    /**
     * 热豆/扳手 转增时检测用户是否实名
     */
    @RepeatSubmit(interval = 1000, justUrl = true)
    @GetMapping("/hotBeansRecipientRealName/{userId}")
    @ApiOperation("热豆/扳手/力豆 转赠被赠用户实名信息")
    public R<HotBeansRecipientRealNameVo> hotBeansRecipientRealName(@PathVariable("userId") Long userId) {
        SysUser giveUser = sysUserService.selectUserById(getUserId());
        SysUser sysUser = sysUserService.selectUserById(userId);
        if (null == sysUser) {
            throw new ServiceException("未识别到当前账户");
        }
        if (giveUser.getUserId().equals(sysUser.getUserId())){
            throw new ServiceException("自己不能作为转赠对象");
        }
        HotBeansRecipientRealNameVo vo = new HotBeansRecipientRealNameVo();
        vo.setNickName(sysUser.getNickName());

        ConsumerRealName userRealNameOrNull = realNameService.getUserRealNameOrNull(userId);
        if (userRealNameOrNull != null) {
            // 脱敏
            userRealNameOrNull.setIdCardName(null);
            userRealNameOrNull.setIdCard(null);
            userRealNameOrNull.setIdCardUrl(null);
            userRealNameOrNull.setIdCardOppositeUrl(null);
        }
        vo.setConsumerRealName(userRealNameOrNull);
        return R.ok(vo);
    }


    /**
     * 热豆热豆转增确认
     *
     * @param
     * @return
     */
    @RepeatSubmit(interval = 1000, justUrl = true)
    @PostMapping("/hotBeansGive")
    @ApiOperation("用户热豆转赠确认")
    public R hotBeansGive(@Validated @RequestBody AesParams param) {
        Long userId = getUserId();
        HotBeansGiveDto dto = AesUtil.decryptToObject(param.getParamStr(), HotBeansGiveDto.class);
        // 校验支付密码
        sysUserService.checkPayPwd(userId, dto.getPayPwd());
//        userId = 2l;
        try {
            basicService.hotBeansGive(dto, userId);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return R.fail(HttpStatus.ERROR, e.getMessage());
        }
        return R.ok_msg("转赠成功");
    }



    /**
     * 扳手转增确认
     *
     * @param
     * @return
     */
    @RepeatSubmit(interval = 1000, justUrl = true)
    @PostMapping("/wrenchGive")
    @ApiOperation("用户扳手转赠确认")
    public R wrenchGive(@Validated @RequestBody AesParams param) {
        Long userId = getUserId();
        HotBeansGiveDto dto = AesUtil.decryptToObject(param.getParamStr(), HotBeansGiveDto.class);
        // 校验支付密码
        sysUserService.checkPayPwd(userId, dto.getPayPwd());
        try {
            basicService.wrenchGive(dto, userId);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return R.fail(HttpStatus.ERROR, e.getMessage());
        }
        return R.ok("转赠成功");
    }

    @RepeatSubmit(interval = 1000, justUrl = true)
    @PostMapping("/lidouGive")
    @ApiOperation("用户力豆转赠确认")
    public R give(@Validated @RequestBody AesParams param) {
        Long userId = getUserId();
        HotBeansGiveDto dto = AesUtil.decryptToObject(param.getParamStr(), HotBeansGiveDto.class);
        // 校验支付密码
        sysUserService.checkPayPwd(userId, dto.getPayPwd());
        sysUserLidouRecordService.give(dto, userId);
        return R.ok();
    }

}
